package com.xingxue.rbac.service.impl;

import com.xingxue.rbac.dao.OrgDao;
import com.xingxue.rbac.dao.impl.OrgDaoImpl;
import com.xingxue.rbac.entity.Org;
import com.xingxue.rbac.service.OrgService;

import java.util.*;

/**
 * 实现类1：基于递归的实现，较难理解
 * @author yihang
 */
public class OrgServiceImplRecursion implements OrgService {
    private OrgDao orgDao = new OrgDaoImpl();

    @Override
    public Collection<Org> findTree() {
        List<Org> all = orgDao.findAll();
        // 父元素集合
        Set<Org> parents = new LinkedHashSet<>();
        // 剩余元素集合
        Set<Org> rests = new LinkedHashSet<>();
        // 先过滤一遍，将元素拆分为两个集合
        for (Org org : all) {
            if (org.getPid() == -1) {
                parents.add(org);
            } else {
                rests.add(org);
            }
        }
        build(parents, rests);
        return parents;
    }

    private void build(Set<Org> parents, Set<Org> rests) {
        // 剩余集合没有元素，结束递归
        if (rests.size() == 0) {
            return;
        }
        // 下一层父元素集合
        Set<Org> nextParents = new LinkedHashSet<>();
        // 下一层剩余元素集合
        Set<Org> nextRests = new LinkedHashSet<>();
        // 将剩余集合继续拆分为两个集合
        for (Org rest : rests) {
            for (Org parent : parents) {
                if (rest.getPid() == parent.getId()) {
                    // 建立父子关系
                    parent.getChildren().add(rest);
                    nextParents.add(rest);
                } else {
                    nextRests.add(rest);
                }
            }
        }
        build(nextParents, nextRests);
    }

    public static void main(String[] args) {
        OrgService service = new OrgServiceImplRecursion();
        Collection<Org> tree = service.findTree();
        for (Org o1 : tree) {
            System.out.println(o1);
            for (Org o2 : o1.getChildren()) {
                System.out.println("\t" + o2);
                for (Org o3 : o2.getChildren()) {
                    System.out.println("\t\t" + o3);
                    for (Org o4 : o3.getChildren()) {
                        System.out.println("\t\t\t" + o4);
                    }
                }
            }
        }
    }
}
